﻿; (function (global) {

    'use strict';
    //1---5---7-7-914-5---3-7-1--76-581-9-9-------838-7-9-1---7--54---3-8-7-6-2---9---5
    //perfs 10 000 ,chrome 200 ms (2,3,4) , chrome 100 ms (2,3)

    global.Strategies = global.Strategies || {};

    Strategies.NakedPair = function NakedPair() {
        this.type = 'elimination';
    }

    Strategies.NakedPair.prototype.perform = function (grid) {

        var result = this.performByRows(grid);
        if (result)
            return result;

        result = this.performByColumns(grid);
        if (result)
            return result;

        result = this.performByRegions(grid);
        if (result)
            return result;

        return null;
    }

    Strategies.NakedPair.prototype.performByRows = function (grid) {
        return this.performOnCellsUnit(grid, grid.cells);
    }

    Strategies.NakedPair.prototype.performByColumns = function (grid) {
        return this.performOnCellsUnit(grid, grid.cellsByColumn);
    }

    Strategies.NakedPair.prototype.performByRegions = function (grid) {
        return this.performOnCellsUnit(grid, grid.cellsByRegion);
    }

    Strategies.NakedPair.prototype.performOnCellsUnit = function (grid, alignedCellsByIndex) {

        for (var i = 0; i < 9; i++) {
            var alignedCells = alignedCellsByIndex[i];
            var emptyCells = SolvingHelper.getEmptyCells(alignedCells);

            var result = this.performOnEmptyCellsGroup(emptyCells)
            if (result) {
                return result;
            }
        }

        return null;
    }

    Strategies.NakedPair.prototype.performOnEmptyCellsGroup = function (emptyCells) {

        var emptyLength = emptyCells.length;
        if (emptyCells.length < 3)
            return false;

        var set = new LazyValuesSet();

        for (var c = 2; c < 5; c++) {
            var emptyCellsForC = [];

            for (var i = 0; i < emptyLength; i++) {
                var cell = emptyCells[i];
                if (cell.candidates.count <= c) {
                    emptyCellsForC.push(cell);
                }
            }

            var emptyLengthForC = emptyCellsForC.length;
            if (emptyLengthForC < c || c === emptyLength)
                continue;

            var combinations = CombinationGenerator.getArray(c, emptyLengthForC);

            for (var i = 0; i < combinations.length; i++) {
                var combination = combinations[i];
                set.clear();
                var discard = false;

                for (var j = 0; j < c; j++) {
                    var cell = emptyCellsForC[combination[j]];

                    for (var can = 0; can < cell.candidates.count ; can++) {
                        var candidate = cell.candidates.values[can];
                        if (set.add(candidate)) {
                            if (set.count > c) {
                                discard = true;
                                break;
                            }
                        }
                    }

                    if (discard)
                        break;
                }

                if (!discard && set.count == c) {
                    var inspectedCells = [];
                    for (var j = 0; j < c; j++) {
                        var cell = emptyCellsForC[combination[j]];
                        inspectedCells.push(cell);
                    }

                    var result = SolvingHelper.removeRangeFromOtherCells(set.getValues(), inspectedCells, emptyCells)
                    if (result) {
                        return { candidates: set.getValues(), containingCells: inspectedCells, targetCells: emptyCells }

                    }
                }

            }
        }

        return null;
    }

}(this));
